package com.flynn.rock.system.service.impl;

import com.flynn.rock.model.PageResult;
import com.flynn.rock.model.dto.OperateLogDto;
import com.flynn.rock.system.convert.AbstractOperateLogConvert;
import com.flynn.rock.system.entity.SysOperateLogEntity;
import com.flynn.rock.system.model.OperateLogCriteria;
import com.flynn.rock.system.model.request.PageOperateLogRequest;
import com.flynn.rock.system.model.vo.OperateLogVo;
import com.flynn.rock.system.repository.SysOperateLogRepository;
import com.flynn.rock.system.service.SysOperateLogService;
import com.flynn.rock.util.JpaQueryHelper;
import com.flynn.rock.util.PageUtil;
import jakarta.annotation.Resource;
import jakarta.persistence.criteria.Path;
import jakarta.persistence.criteria.Predicate;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

@Service
public class SysOperateLogServiceImpl implements SysOperateLogService {

    @Resource
    private SysOperateLogRepository sysOperateLogRepository;

    @Override
    public void saveOperateLog(OperateLogDto operateLog) {
        SysOperateLogEntity entity = AbstractOperateLogConvert.INSTANCE.toOperateLogEntity(operateLog);
        sysOperateLogRepository.save(entity);
    }

    @Override
    public PageResult<OperateLogVo> pageOperateLog(PageOperateLogRequest request) {
        OperateLogCriteria criteria = OperateLogCriteria.builder()
                .operateTitle(request.getOperateTitle())
                .status(request.getStatus())
                .build();
        PageRequest pageRequest = PageRequest.of(request.getPageNum() - 1, request.getPageSize());
        pageRequest = pageRequest.withSort(Sort.sort(SysOperateLogEntity.class).by(SysOperateLogEntity::getUpdateTime).descending());
        Page<SysOperateLogEntity> entityPage = sysOperateLogRepository.findAll(
                ((root, query, criteriaBuilder) -> {
                    List<Predicate> predicates = new ArrayList<>();
                    Path<Object> operateType = root.get("operateType");
                    if (Objects.nonNull(request.getOperateType())) {
                        predicates.add(criteriaBuilder.equal(operateType, request.getOperateType()));
                    }
                    predicates.add(JpaQueryHelper.getPredicate(root, criteria, criteriaBuilder));
                    return criteriaBuilder.and(predicates.toArray(new Predicate[0]));
                }),
                pageRequest
        );
        return PageUtil.toPage(entityPage.map(AbstractOperateLogConvert.INSTANCE::toOperateLogVo));
    }
}
